package com.ihr360.payroll.model.dto.salary.plan;

import com.fasterxml.jackson.annotation.JsonIgnore;
import com.google.common.collect.Lists;
import com.ihr360.authority.sharing.model.IResourceControl;
import com.ihr360.authority.sharing.model.ResourceAccess;
import com.ihr360.commons.lang.CollectionUtils;
import com.ihr360.commons.model.entity.NumberIdWithTime;
import com.ihr360.payroll.model.base.salaryreport.ISalaryPlan;
import com.ihr360.payroll.model.dto.salary.plan.config.PayslipConfig;
import lombok.Getter;
import lombok.Setter;

import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Embedded;
import javax.persistence.FetchType;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToMany;
import javax.persistence.MappedSuperclass;
import javax.persistence.OneToMany;
import javax.persistence.Transient;
import java.util.List;

/**
 * 薪酬方案
 */
@Getter
@Setter
@MappedSuperclass
public class AbstractSalaryPlan extends NumberIdWithTime<Long> implements ISalaryPlan,IResourceControl {

    public static final class Field{
        public final static String enabled = "enabled";
    }

    public static class CycleMonth {
        /** 上上月 */
        public final static int BEFORE_LAST = -2;
        /** 上月 */
        public final static int LAST = -1;
        /** 本月 */
        public final static int THIS = 0;
        /** 下月 */
        public final static int NEXT = 1;
    }

    /** 名称 */
    @Column(length = 50, nullable = false)
    private String name;

    /** 备注*/
    @Column(length = 2000)
    private String remark;

    /** 工资单配置 */
    @ManyToMany(fetch = FetchType.LAZY, cascade = CascadeType.REMOVE)
    private List<PayslipConfig> payslipConfigs;


    @OneToMany(fetch = FetchType.LAZY)
    @JoinColumn(name = "salaryPlanId")
    private List<SalaryPlanStaff> staffs;


    /** 是否启用*/
    private boolean enabled = true;


    /** 是否每月发放一次 */
    private boolean monthCycle = true;

    /** 算薪周期月 */
    private Integer calculateCycleMonth;

    /** 算薪周期天 */
    private Integer calculateCycleDay;

    /** 考勤周期月 */
    private Integer attendanceCycleMonth;

    /** 考勤周期天 */
    private Integer attendanceCycleDay;

    /** 薪资所属月份 -1 上月 0 本月 1 下月 */
    @Column(columnDefinition = "int(11) default 0")
    private Integer salaryMonth = 0;

    /** 是否引用福利数据*/
    @Column(columnDefinition = "bit(1) default 0")
    private boolean referenceBenefitData;

    @Transient
    private Integer staffNumber;

    @Transient
    private Integer payPeriodStaffNumber;

    @Embedded
    private ResourceAccess resourceAccess;

    @Override
    public ResourceAccess getResourceAccess() {
        if (resourceAccess == null) {
            resourceAccess = new ResourceAccess();
        }
        return resourceAccess;
    }

    @Override
    public void setResourceAccess(ResourceAccess resourceAccess) {
        this.resourceAccess = resourceAccess;
    }

//    /** 账期内员工 */
//    @ManyToMany(fetch = FetchType.LAZY)
//    @JoinTable(name = "salaryplan_staff",
//            joinColumns = @JoinColumn(name = "salaryplanId"),
//            inverseJoinColumns = @JoinColumn(name = "staffId")
//    )
//    private List<SyncedBasicStaffInfo> staffs;


    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public boolean isMonthCycle() {
        return monthCycle;
    }

    public void setMonthCycle(boolean monthCycle) {
        this.monthCycle = monthCycle;
    }

    public List<PayslipConfig> getPayslipConfigs() {
        return payslipConfigs;
    }

    public void setPayslipConfigs(List<PayslipConfig> payslipConfigs) {
        this.payslipConfigs = payslipConfigs;
    }

    public String getRemark() {
        return remark;
    }

    public void setRemark(String remark) {
        this.remark = remark;
    }

    public boolean isEnabled() {
        return enabled;
    }

    public void setEnabled(boolean enabled) {
        this.enabled = enabled;
    }

    public Integer getCalculateCycleMonth() {
        return calculateCycleMonth;
    }

    public void setCalculateCycleMonth(Integer calculateCycleMonth) {
        this.calculateCycleMonth = calculateCycleMonth;
    }

    public Integer getCalculateCycleDay() {
        return calculateCycleDay;
    }

    public void setCalculateCycleDay(Integer calculateCycleDay) {
        this.calculateCycleDay = calculateCycleDay;
    }

    public Integer getAttendanceCycleMonth() {
        return attendanceCycleMonth;
    }

    public void setAttendanceCycleMonth(Integer attendanceCycleMonth) {
        this.attendanceCycleMonth = attendanceCycleMonth;
    }

    public Integer getAttendanceCycleDay() {
        return attendanceCycleDay;
    }

    public void setAttendanceCycleDay(Integer attendanceCycleDay) {
        this.attendanceCycleDay = attendanceCycleDay;
    }

    @JsonIgnore
    public List<SalaryPlanStaff> getStaffs() {
        return staffs;
    }

    @JsonIgnore
    private synchronized void staffs2Number(){
        if(staffNumber != null || payPeriodStaffNumber != null) {
            return;
        }
        staffNumber = 0;
        payPeriodStaffNumber = 0;
        if(!CollectionUtils.isEmpty(staffs)) {
            for (SalaryPlanStaff staff : staffs) {
                if (staff.getStaffState() != SalaryPlanStaff.StaffState.TEMP_ADD) {
                    staffNumber++;
                }
                if (staff.getStaffState() != SalaryPlanStaff.StaffState.TEMP_REMOVE) {
                    payPeriodStaffNumber++;
                }
            }
        }
    }

    @JsonIgnore
    public int getStaffNumber() {
        staffs2Number();
        return staffNumber;
    }

    @JsonIgnore
    public int getPayPeriodStaffNumber() {
        staffs2Number();
        return payPeriodStaffNumber;
    }

    @JsonIgnore
    public List<String> getStaffIdList() {
        List<String> staffIdList = Lists.newArrayList();
        if(CollectionUtils.isNotEmpty(staffs)) {
            for (SalaryPlanStaff salaryPlanStaff:staffs) {
                staffIdList.add(salaryPlanStaff.getStaffId());
            }
        }
        return staffIdList;
    }
}